/*
 * rosterwindow.cpp - roster window class
 * Copyright (C) 2009  Sergei Stolyarov
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * Kajim::ChatInputText widget implements basic functions required
 * by chat text entry widget: history navigation, autocompletion etc
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <QtGui>
#include <QtDebug>
#include <QThread>
#include "rosterwindow.h"
#include "preferencesdialog.h"
#include "accountstore.h"
#include "xmpp/connection.h"
#include "xmpp/connectionstore.h"
#include "accountsdialog.h"
#include "settings.h"
#include "widgets/rosterwidget.h"


RosterWindow::RosterWindow()
    : QMainWindow(), tabs(0)
{
    rosterWidget = new RosterWidget(this);
    rosterWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
    rosterWidget->setMinimumWidth(100);
    splitter = new QSplitter(this);
    splitter->setOrientation(Qt::Horizontal);
    splitter->addWidget(rosterWidget);
    splitter->setChildrenCollapsible(false);
    setCentralWidget(splitter);

    createActions();
    createMenus();
    createTrayIcon();

    trayIcon->show();

    restoreGeometry();
}

void RosterWindow::addTabsWidget(QTabWidget * widget)
{
    if (tabs != 0) {
        return;
    }
    tabs = widget;
    splitter->insertWidget(0, tabs);
}

void RosterWindow::removeTabsWidget()
{
    if (tabs == 0) {
        return;
    }
    delete tabs;
    tabs = 0;
}

QTabWidget * RosterWindow::tabsWidget()
{
    return tabs;
}

//! \brief Display preferences dialog.
void RosterWindow::preferences()
{
    PreferencesDialog dialog(this);
    dialog.exec();
}

//! \brief Quit application, display confirmation message box etc.
void RosterWindow::quit()
{
    rememberGeometry();
    // disconnect all accounts
    rosterWidget->logoutAll();
    Kajim::Settings::sync();
    // TODO: wait for all connections close
    Kajim::AccountStore * accountStore = Kajim::AccountStore::instance();
    Kajim::XMPP::ConnectionStore * connectionStore = Kajim::XMPP::ConnectionStore::instance();

    QList<Kajim::XMPP::Connection*> connections;

    Q_FOREACH(int h, accountStore->accountsList()) {
        connections.append(connectionStore->accountConnection(h));
    }

    // stupid method to emulate sleep() function
    QWaitCondition sleep;
    QMutex mutex;
    mutex.lock();

    // wait untill all connections are closed
    int quit_timeout = Kajim::Settings::get("ui/quit_timeout").toInt();
    for (int i=0; i<quit_timeout; i++) {
        bool all_offline = true;
        Q_FOREACH(Kajim::XMPP::Connection * conn, connections) {
            if (conn->isConnected()) {
                all_offline = false;
                break;
            }
        }
        if (all_offline) {
            break;
        }
        sleep.wait(&mutex, 1000); // wait for 1 second
    }
    QCoreApplication::quit();
}

//! \brief Display accounts editing dialog.
void RosterWindow::editAccounts()
{
    AccountsDialog dialog(this);
    dialog.exec();
}

//! \brief Display "About" dialog
void RosterWindow::about()
{
    QMessageBox::about(this, tr("About Kajim"), tr("Kajim: Jabber Client"));
}

void RosterWindow::closeEvent(QCloseEvent * event)
{
    rememberGeometry();
    event->ignore();
    hide();
}

//! \brief Create action and connect signals.
void RosterWindow::createActions()
{
    preferencesAction = new QAction(tr("&Preferences"), this);
    connect(preferencesAction, SIGNAL(triggered()), this, SLOT(preferences()));

    quitAction = new QAction(tr("&Quit"), this);
    quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
    connect(quitAction, SIGNAL(triggered()), this, SLOT(quit()));

    accountsAction = new QAction(tr("&Accounts"), this);
    connect(accountsAction, SIGNAL(triggered()), this, SLOT(editAccounts()));

    aboutAction = new QAction(tr("&About"), this);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

    toggleRosterAction = new QAction(tr("&Toggle roster window"), this);
    connect(toggleRosterAction, SIGNAL(triggered()), this, SLOT(toggleRosterWindow()));
}

void RosterWindow::createMenus()
{
    QMenuBar * menuBar = new QMenuBar();
    QMenu * fileMenu = new QMenu(tr("&File"), this);
    fileMenu->addAction(quitAction);
    menuBar->addMenu(fileMenu);

    QMenu * editMenu = new QMenu(tr("&Edit"), this);
    editMenu->addAction(accountsAction);
    editMenu->addAction(preferencesAction);
    menuBar->addMenu(editMenu);

    QMenu * helpMenu = new QMenu(tr("&Help"), this);
    helpMenu->addAction(aboutAction);
    menuBar->addMenu(helpMenu);

    this->setMenuBar(menuBar);
}

void RosterWindow::createTrayIcon()
{
    QMenu * trayMenu = new QMenu();
    trayMenu->addAction(toggleRosterAction);
    trayMenu->addSeparator();
    trayMenu->addAction(quitAction);

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/main-icon-16x16.png"));
    trayIcon->setContextMenu(trayMenu);
}

void RosterWindow::rememberGeometry()
{
    QSize s = size();
    QPoint p = pos();

    Kajim::Settings::set("rosterwindow/size", s);
    Kajim::Settings::set("rosterwindow/pos", p);
}

void RosterWindow::restoreGeometry()
{
    QSize s = Kajim::Settings::get("rosterwindow/size").toSize();
    QPoint p = Kajim::Settings::get("rosterwindow/pos").toPoint();

    resize(s);
    move(p);
}

void RosterWindow::toggleRosterWindow()
{
    if (isVisible()) {
        hide();
    } else {
        show();
    }
}
